package com.tianquan.miracle.beans;/**
 * @author starsea
 * @date 2024-10-11 下午12:26
 */

import com.tianquan.miracle.aop.AopEntity;
import com.tianquan.miracle.conditional.parseConditionPostProcessor;
import com.tianquan.miracle.postprocessor.BeanPostProcessor;
import com.tianquan.miracle.postprocessor.InjectBeanPostProcessor;
import com.tianquan.miracle.proxy.PoxyFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @BelongsProject: uploaddemo
 * @BelongsPackage: com.tianquan.miracle.context
 * @Author: tianquan
 * @CreateTime: 2024-10-11  12:26
 * @Description: 通用的bean处理器
 * @Version: 1.0
 */
public abstract class AbstractCommonBeanProcessor {

    // 依赖注入处理器
    final List<InjectBeanPostProcessor> injectBeanPostProcessors = new ArrayList<>(16);

    // 解析Condition系列注解
    final List<parseConditionPostProcessor> parseConditionPostProcessors = new ArrayList<>(16);

    // 需要走代理的注解,容器启动先去拿到所有切点里的注解
    final Map<Class<? extends Annotation>, AopEntity> aopAnnotationMap = new HashMap<>();

    // 需要走代理的方法
    final Map<String, AopEntity> aopMethodsNameMap = new HashMap<>();

    // 需要走代理的类,加强里面所有的方法
    final Map<Class<?>, AopEntity> aopClassMap = new HashMap<>();

    // bean的后置处理器
    final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>(16);

    public void putAopAnnotationName(Class<? extends Annotation> annotation, AopEntity aopEntity) {
        aopAnnotationMap.put(annotation, aopEntity);
    }

    public void putAopMethodsName(String method, AopEntity aopEntity) {
        aopMethodsNameMap.put(method, aopEntity);
    }

    public void putAopClass(Class<?> className, AopEntity aopEntity) {
        aopClassMap.put(className, aopEntity);
    }

    public void addInjectBeanPostProcessors(List<InjectBeanPostProcessor> beanPostProcessors) {
        this.injectBeanPostProcessors.addAll(beanPostProcessors);
    }

    public void addParseConditionPostProcessors(List<parseConditionPostProcessor> beanPostProcessors) {
        this.parseConditionPostProcessors.addAll(beanPostProcessors);
    }

    protected Object isNecessaryCreateProxy(Object bean) {
        Class<?> aClass = bean.getClass();
        // 当前bean的所有方法
        List<String> currentBeanAllMethods = Arrays.stream(bean.getClass().getDeclaredMethods())
                .map(Method::getName).collect(Collectors.toList());

        // 整个类的方法是否都要增强
        AopEntity aopEntity = aopClassMap.get(aClass);
        if (aopEntity != null) return PoxyFactory.getProxy(bean, currentBeanAllMethods,
                aopEntity.getBeforeMethod(), aopEntity.getAroundMethod(), aopEntity.getAfterMethod(), aopEntity.getObject()
        );

        // 某些方法需要生成代理
        List<String> proxyMethods = aopMethodsNameMap.keySet().stream()
                .filter(methodName -> currentBeanAllMethods.stream().anyMatch(poxyMethodName -> poxyMethodName.equals(methodName)))
                .collect(Collectors.toList());

        if (!proxyMethods.isEmpty()) aopEntity = aopMethodsNameMap.get(proxyMethods.get(0));

        // 注解
        for (Method method : aClass.getDeclaredMethods())
            for (Annotation annotation : method.getAnnotations()) {
                aopEntity = aopAnnotationMap.get(annotation.annotationType());
                if (aopEntity == null) continue;
                proxyMethods.add(method.getName());
                break;
            }

        if (!proxyMethods.isEmpty()) return PoxyFactory.getProxy(bean, proxyMethods,
                aopEntity.getBeforeMethod(), aopEntity.getAroundMethod(), aopEntity.getAfterMethod(), aopEntity.getObject()
        );

        // 不需要走代理
        return bean;
    }

    public List<BeanPostProcessor> getBeanPostProcessors() {
        return beanPostProcessors;
    }

    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        beanPostProcessors.add(beanPostProcessor);
    }

    public abstract <T> List<T> selectBean(Class<T> beanClass);
}
